package vn.com.demand.widget;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.regex.Pattern;

import org.apache.commons.dbutils.ResultSetHandler;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import vn.com.demand.util.DpUtils;

public class SelectMultiItemTable extends Composite {

	private List list;
	private Table table;
	private final FormToolkit toolkit = new FormToolkit(Display.getCurrent());
	private TableViewer tableViewer;
	private ItemBrowserCommand command;
	private MyViewerFilter filter;

	/**
	 * Create the composite
	 * @param parent
	 * @param style
	 * @throws SQLException 
	 */
	public SelectMultiItemTable(Composite parent, int style, String sql) throws SQLException {
		super(parent, style);
		setLayout(new FormLayout());
		command = new ItemBrowserCommand(sql, null, new MyModel());
		createContent();
		//
	}
	
	public SelectMultiItemTable(Composite parent, int style, ItemBrowserCommand command) throws SQLException {
		super(parent, style);
		setLayout(new FormLayout());
		this.command = command;
		createContent();
		//
	}
	
	public SelectMultiItemTable(Composite parent, int style) throws SQLException {
		super(parent, style);
		setLayout(new FormLayout());
		toolkit.adapt(this);
		toolkit.paintBordersFor(this);
		createContent();
		//
	}

	private void createContent() throws SQLException {
		final Composite composite = new Composite(this, SWT.NONE);
		composite.setLayout(new FillLayout());
		final FormData fd_composite = new FormData();
		fd_composite.bottom = new FormAttachment(100, 0);
		fd_composite.right = new FormAttachment(100, -245);
		fd_composite.top = new FormAttachment(0, 0);
		fd_composite.left = new FormAttachment(0, 0);
		composite.setLayoutData(fd_composite);
		toolkit.adapt(composite);

		tableViewer = new TableViewer(composite, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
		table = tableViewer.getTable();
		toolkit.adapt(table, true, true);
		table.setLinesVisible(true);
		table.setHeaderVisible(true);

		final TableColumn newColumnTableColumn = new TableColumn(table, SWT.NONE);
		newColumnTableColumn.setWidth(100);
		newColumnTableColumn.setText("Code");

		final TableColumn newColumnTableColumn_1 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_1.setWidth(150);
		newColumnTableColumn_1.setText("Description");

		final Composite composite_1 = toolkit.createComposite(this, SWT.NONE);
		final FillLayout fillLayout = new FillLayout(SWT.VERTICAL);
		fillLayout.spacing = 2;
		composite_1.setLayout(fillLayout);
		final FormData fd_composite_1 = new FormData();
		fd_composite_1.bottom = new FormAttachment(0, 235);
		fd_composite_1.left = new FormAttachment(100, -245);
		fd_composite_1.right = new FormAttachment(100, -210);
		fd_composite_1.top = new FormAttachment(0, 110);
		composite_1.setLayoutData(fd_composite_1);
		toolkit.paintBordersFor(composite_1);

		final Button button = toolkit.createButton(composite_1, ">", SWT.NONE);
		button.setToolTipText("Add selected items to list");
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				addSelectedItems();
			}
		});

		final Button button_2 = toolkit.createButton(composite_1, ">>", SWT.NONE);
		button_2.setToolTipText("Add all the items from table to list");
		button_2.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				addAllItems();
			}
		});

		final Button button_3 = toolkit.createButton(composite_1, "<<", SWT.NONE);
		button_3.setToolTipText("Remove all items from list");
		button_3.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				removeAllItems();
			}
		});

		final Button button_1 = toolkit.createButton(composite_1, "<", SWT.NONE);
		button_1.setToolTipText("Remove selected items from list");
		button_1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				removeSelectedItems();
			}
		});

		final Composite composite_2 = toolkit.createComposite(this, SWT.NONE);
		composite_2.setLayout(new FormLayout());
		final FormData fd_composite_2 = new FormData();
		fd_composite_2.bottom = new FormAttachment(100, 0);
		fd_composite_2.left = new FormAttachment(composite_1, 0, SWT.RIGHT);
		fd_composite_2.top = new FormAttachment(0, 0);
		fd_composite_2.right = new FormAttachment(100, -5);
		composite_2.setLayoutData(fd_composite_2);
		toolkit.paintBordersFor(composite_2);

		final Section selectedItemsSection = toolkit.createSection(composite_2, Section.EXPANDED | Section.TITLE_BAR | Section.FOCUS_TITLE);
		final FormData fd_selectedItemsSection = new FormData();
		fd_selectedItemsSection.right = new FormAttachment(100, -5);
		fd_selectedItemsSection.bottom = new FormAttachment(0, 24);
		fd_selectedItemsSection.top = new FormAttachment(0, 3);
		fd_selectedItemsSection.left = new FormAttachment(0, 3);
		selectedItemsSection.setLayoutData(fd_selectedItemsSection);
		selectedItemsSection.setText("Selected Items");

		list = new List(composite_2, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER);
		final FormData fd_list = new FormData();
		fd_list.bottom = new FormAttachment(100, -5);
		fd_list.right = new FormAttachment(100, -5);
		fd_list.top = new FormAttachment(0, 27);
		fd_list.left = new FormAttachment(0, 3);
		list.setLayoutData(fd_list);
		toolkit.adapt(list, true, true);
		
		tableViewer.setLabelProvider(new MyLabelProvider());
		tableViewer.setContentProvider(new MyContentProvider());
		tableViewer.setInput(createModel());

		filter = new MyViewerFilter(null);
		tableViewer.setFilters(new ViewerFilter[] { filter });
	}
	
	protected void removeSelectedItems() {
		String[] selection = list.getSelection();
		if (null != selection && 0 < selection.length) {
			for (int i = 0; i < selection.length; i++) {
				list.remove(selection[i]);
			}
		}
	}

	protected void removeAllItems() {
		list.removeAll();
	}
	
	protected void addSelectedItems() {
		TableItem[] tableItems = table.getSelection();
		if (null != tableItems && 0 < tableItems.length) {
			for (int i = 0; i < tableItems.length; i++) {
				MyModel str = (MyModel) tableItems[i].getData();
				list.add(str.code);
			}
		}
	}

	protected void addAllItems() {
		TableItem[] items = table.getItems();
		if (null != items && 0 < items.length) {
			list.removeAll();
			for (int i = 0; i < items.length; i++) {
				MyModel data = (MyModel) items[i].getData();
				list.add(data.code);
			}
		}
	}
	
	private class MyViewerFilter extends ViewerFilter {

		private String filterValue;
		private Pattern codePattern;
		private Pattern descriptionPattern;

		public MyViewerFilter(String filterValue) {
			setFilterValue(filterValue);
		}

		@Override
		public boolean select(Viewer arg0, Object parentElement, Object element) {
			if (null == filterValue) {
				return true;
			}
			MyModel model = (MyModel) element;
			if (codePattern.matcher(model.code).find()
					|| (null != model.description && descriptionPattern
							.matcher(model.description).find())) {
				return true;
			}
			return false;
		}

		public void setFilterValue(String value) {
			filterValue = value;
			codePattern = Pattern.compile(filterValue + ".*",
					Pattern.CASE_INSENSITIVE);
			descriptionPattern = Pattern.compile(".*" + filterValue + ".*",
					Pattern.CASE_INSENSITIVE);
		}
	};
	
	private class MyContentProvider implements ITreeContentProvider {

		public Object[] getChildren(Object arg0) {
			return null;
		}

		public Object getParent(Object arg0) {
			return null;
		}

		public boolean hasChildren(Object arg0) {
			return false;
		}

		public Object[] getElements(Object myModelArr) {
			return (Object[]) myModelArr;
		}

		public void dispose() {

		}

		public void inputChanged(Viewer arg0, Object arg1, Object arg2) {

		}

	}

	private MyModel[] createModel() throws SQLException {
		return (MyModel[]) command.execute(new MyModel());
	}

	private class MyLabelProvider extends LabelProvider implements
			ITableLabelProvider {

		public Image getColumnImage(Object arg0, int arg1) {
			return null;
		}

		public String getColumnText(Object model, int column) {
			switch (column) {
			case 0:
				return ((MyModel) model).code;
			case 1:
				return ((MyModel) model).description;
			default:
				break;
			}
			return null;
		}

	}

	class MyModel implements ResultSetHandler {

		String code;
		String description;

		public Object handle(ResultSet rs) throws SQLException {
			ArrayList<MyModel> list = new ArrayList<MyModel>();
			while (rs.next()) {
				MyModel model = new MyModel();
				model.code = DpUtils.trim(rs.getString(1));
				model.description = DpUtils.trim(rs.getString(2));
				list.add(model);
			}
			return list.toArray(new MyModel[0]);
		}

		
		public String getCode() {
			return code;
		}

		public void setCode(String code) {
			this.code = code;
		}

		public String getDescription() {
			return description;
		}

		public void setDescription(String description) {
			this.description = description;
		}

		@Override
		public String toString() {
			return code + " = " + description;
		}
	}

	@Override
	public void dispose() {
		super.dispose();
	}

	@Override
	protected void checkSubclass() {
		// Disable the check that prevents subclassing of SWT components
	}

	public Object[] getChildren(Object arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object getParent(Object arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean hasChildren(Object arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	public Object[] getElements(Object arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
		// TODO Auto-generated method stub

	}

	public String[] getSelectedItemsCode() {
		return list.getItems();
	}

	public void setSelectedItem(String value) {

	}

	public void setFilterValue(String value) {
		filter.setFilterValue(value);
		tableViewer.refresh();
	}

}
